/*
 *@# Agency Created on 2004-7-28
 *
 *
 * Copyright: Bluejay Networks Inc. & Inquiry Management Systems Ltd.  2004
 *
 * This software is the proprietary information of Bluejay Networks Inc. & 
 * Inquiry Management Systems Ltd.  
 * Use is subject to license terms.
 */
package com.ims.iaa.AD;

import com.ims.iaa.IaaDebug; 
import com.ims.iaa.IaaUtil; 
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * This class dsscribe the common character of advertisement data such as image
 * and flash. If store in database option is choosed, 
 * the serialized fields in this class will be stored into the tblImage and 
 * tblImageData table. The database access is delegated to the server-side 
 * service <code>SpiderDBConnection</code>. This class can be serialized and 
 * sent to a different JVM.
 * 
 * the AdFlash class and AdImage class extends it.
 *
 * @see AdImage
 * @see AdFlash
 * 
 * @author ShengMeng Bai
 * @version 1.0
 */
public abstract class AdData implements Serializable{

	/**
	  * Constant indicate height, width unknown due to the construction 
	  * of the image(or flash) has not finished yet
	  *
	  */
	static public final int UNKNOWN  = -1;
	 /**
	   * Constant indicate height, width unknown due to no data exist at all
	   */
	static public final int NOTEXIST = -999;
	/** 
	  * Array contains the actual data. Usually the size of this array 
	  * should equals to the value of m_iDataSize. However even no data exist,
	  * the m_iDataSize might be available. Check #m_iDataSize for detail.
	  *
	  * @see #setData
	  * @see #getData	  	  
	  */
   private byte[] m_bytData;

   /**
	  * Flash digested signature used to distinguish data. 
	  * This signature is digested using SHA algorithm (provided by JDK 1.3)
	  * on the <code>m_bytData</code> field. According to the algorithm, 
	  * different input data generally generate different digest information.
	  * It provide an efficient way to distingush between different data.
	  *
	  */
	private byte[] m_bytSignature;

	/** 
	  * data size in bytes. Usually  equals to the size of the m_bytData. 
	  * if the data is image , it Maybe collected from other way if no image data exist,
	  * if the data is flash, it should equals to the size of the m_bytData.
	  * Check #m_bytData for detail.
      *
	  * @see #setDataSize
	  * @see #getDataSize	  	  
	  */
   private int m_iDataSize;
	
	/**
	  * Image(or flash) height in pixels. NOTEXIST if no image(or flash) data exist. 
	  * UNKNOWN if unknown yet. if the data is image, it Usually set by the 
	  * <code>imageUpdate</code> method in<code>AdImage</code> class.
	  *
	  * @see #getImageHeight
	  * @see #setImageHeight
	  * @see AdImage#imageUpdate
	  * @see #NOTEXIST
	  * @see #UNKNOWN
	  */
	private int m_iWidth = UNKNOWN;
	private int m_iHeight = UNKNOWN;
	/** 
	 * The data type, if it is image, may be "image/gif" or "image/jpeg". 
	 * if it is Flash should be "application/x-shockwave-flash",
	 * Empty string if unknown. 
	 *
	 */
	private String m_sDataType = "";
	
    /**
     * Set the actual data,
     * but AdImage will override this method to do some special thing,
     * chack the <code>setData</code>method of the <code>AdImage</code> class for detail. 
	 *
     * @param bytData an array of bytes
     *
     * @return void
     */
	public void setData(byte[] bytData)  {
		m_bytData = bytData;
	}
   /**
    * Provides a <code>ByteArrayInputStream</code> contains the flash data. 
	*
    * @return  The <code>ByteArrayInputStream</code> contains the flash data, 
	* or null if no  data present.
    *
    */
	public InputStream getData(){
	   	if (m_bytData == null)  {
	   		return null;
	   	} else  {
	   		return new ByteArrayInputStream(m_bytData);
	   	}
	}
	public byte[] getByteData(){
	    return m_bytData;
	}
	
	/**
	 * Sets the height of the image(or flash). if the data is image,
	 * the height should be set by the <code>imageUpdate</code> method
	 * in<code>AdImage</code> class.
	 *
	 * @param height The int values to be set as the height.
	 *
	 * @return void
	 *
	 */  
	public void setHeight( int iHeight ){
		m_iHeight = iHeight;
	}
	/**
	 * Get image(or flash) height.
	 * @return height in pixels
	 */
	public int getHeight(){
		return m_iHeight;
	}
	

	/**
	 * Sets the width of the image(or flash). if the data is image,
	 * the width should be set by the <code>imageUpdate</code> method
	 * in<code>AdImage</code> class.
	 *
	 * @param width The int values to be set as the height.
	 *
	 * @return void
	 *
	 */  
	public void setWidth( int iWidth ){
		m_iWidth = iWidth;
	}
	/**
	 * Get image(or flash) width
	 * @return width in pixels
	 */
	public int getWidth(){
		return m_iWidth;
	}
	
    /**
     * Sets the image(or flash) size. If the data is image,
     * the size of the image can be get without actually get the image data. 
     * So image size is not seted by the <code>setData
	 * </code> method.
	 *
     * @param size The int value to be set as the image(or flash) size in bytes.
     *
     * @return void
     *
     */
	public void setDataSize( int iSize ){
		m_iDataSize = iSize;
	}
	/**
	 * Get the flash(or image) size
	 * @return size in bytes
	 */
	public int getDataSize(){
		
		//added by Victor May 28, 2009
		if(m_bytData !=null ) {
			if (m_bytData.length != m_iDataSize) {
				IaaUtil.log("Image size inconsistency: buffer array length is "+m_bytData.length+", reported length is "+m_iDataSize);			
			}
			return m_bytData.length;
		} else
			return m_iDataSize;  
	}
	
	/**
     * Sets the image MIME type.
	 * see m_sDataType
	 * @param sType
	 */
	public void setDataType( String sType ){
		m_sDataType = sType;
	}
	
	/**
	 * see m_sDataType
	 * @return
	 */
	public String getDataType(){
		return m_sDataType;
	}

   /**
     * Gets the signature of the data. The signature is digested by SHA
	  * algorithm. The signature provide an efficient way to distingush 
	  * between different flash. 
	  *
     * @return Byte array contains the signature of the flash, or null if
	  * 	either no image data present or no SHA algorithm exist. 20 bytes
	  *     for SHA algorithm.
     *
     */
   public byte[] getSignature() {
	if (( m_bytData != null)) {
		try  {
			// Get a MessageDigest for the SHA algorithm
			MessageDigest algorithm = MessageDigest.getInstance ("SHA");
			// Empty the digest's buffer
			algorithm.reset();
			// Fill the digest's buffer with m_bytSignature to compute a message 
				// digest
			algorithm.update (m_bytData);
			// Generate the digest(does any necessary padding required 
				//by the algorithm)
			m_bytSignature = algorithm.digest();
			if ( IaaDebug.AuxDebug )  {
				StringBuffer hexString = new StringBuffer();
				for (int i = 0; i < m_bytSignature.length; i++) {
					 hexString.append( Integer.toHexString(
						 	0xFF & m_bytSignature[i]));
					 hexString.append (" ");
				}
				IaaUtil.log ("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
				IaaUtil.log ("hexString:"+hexString.toString());				
			}
		} catch (NoSuchAlgorithmException e)  {
			IaaUtil.log("No SHA Algorithm Available " + e);
	   		}
	   	} 
	   	return m_bytSignature;
	}
   /**
    * The method is unuseful to image data, only for flash,
    * so it always return null, in subclass AdFlash, it will be override.
    * 
    * @see AdFlash
    * 
    * @return null
    */
	public String getCodeBase(){
		return null;
	}
}
